#ifndef PREF_ICON_H_
#define PREF_ICON_H_

#include "p_widgets.h"

namespace gpyp {
namespace pref {

class IconView : public Gtk::IconView {
private:
  typedef Gtk::TreeModelColumn<Glib::ustring> TreeModelColumnString;
  typedef Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf> > TreeModelColumnPixbuf;

private:
  Glib::RefPtr<Gtk::IconTheme> theme_;

  TreeModelColumnString         column_name_;
  TreeModelColumnPixbuf         column_pixbuf_;
  Gtk::TreeModelColumnRecord    columnrecord_;
  Glib::RefPtr<Gtk::ListStore>  liststore_;

  sigc::connection conn_theme_changed_;

  void init();

  void reset_from_theme();

public:
  bool get_selected(Glib::ustring &name) const;
  bool set_selected(const Glib::ustring name);

  IconView();
  IconView(const char *const *icon_names);
  IconView(Glib::RefPtr<Gtk::IconTheme> theme);
  virtual ~IconView();
};

class IconSelector : public Gtk::Notebook {
private:
  class PageBase : boost::noncopyable {
  protected:
    virtual bool on_get_selected(Glib::ustring &name) const = 0;
    virtual bool on_set_selected(const Glib::ustring &name) = 0;

  public:
    inline bool get_selected(Glib::ustring &name) const {
      return on_get_selected(name);
    }
    inline bool set_selected(const Glib::ustring &name) {
      return on_set_selected(name);
    }

    inline virtual ~PageBase() {
    }
  };
  class IconViewPage : public PageBase,
                       public Gtk::ScrolledWindow {
  private:
    IconView view_;

  protected:
    inline virtual bool on_get_selected(Glib::ustring &name) const {
      return view_.get_selected(name);
    }
    inline virtual bool on_set_selected(const Glib::ustring &name) {
      return view_.set_selected(name);
    }

  private:
    inline void init() {
      set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
      add(view_);
    }

  public:
    inline IconViewPage() {
      init();
    }
    inline IconViewPage(const char *const *icon_names) :
      view_(icon_names)
    {
      init();
    }
    inline IconViewPage(Glib::RefPtr<Gtk::IconTheme> theme) :
      view_(theme)
    {
      init();
    }
  };
  class OtherPage : public PageBase,
                    public Gtk::VBox {
  private:
    Gtk::Window &parent_;

    Gtk::Image   icon_;
    FileEntry    icon_name_;
    Gtk::Button  icon_open_;

    Gtk::Label   note_;

    DialogWrapper<Gtk::FileChooserDialog> file_dialog_;

  private:
    static Glib::RefPtr<Gdk::Pixbuf> get_invalid_icon();

  protected:
    inline virtual bool on_get_selected(Glib::ustring &name) const {
      if (!icon_name_.get_text().empty()) {
        name = icon_name_.get_text();
        return true;
      }
      return false;
    }
    inline virtual bool on_set_selected(const Glib::ustring &name) {
      if (!name.empty()) {
        icon_name_.set_text(name);
        return true;
      }
      return false;
    }

  private:
    void file_dialog_on_response(int response_id);

    void icon_name_on_changed();
    void icon_open_on_clicked();

  public:
    OtherPage(Gtk::Window &parent);
  };

private:
  Gtk::Window &parent_;

  typedef std::vector<PageBase *> PageList;
  PageList     pages_;

  IconViewPage builtin_;
  IconViewPage user_;
  IconViewPage stock_;
  OtherPage    other_;

public:
  void set_icon_name(const Glib::ustring &name);
  Glib::ustring get_icon_name() const;

  void add();
  void remove();

private:
  template<typename T>
  inline void append_page(T &page, const Glib::ustring &label) {
    page.set_border_width(2);
    pages_.push_back(&page);
    Gtk::Notebook::append_page(page, label);
  }

public:
  IconSelector(Gtk::Window &parent);
};

class IconSelectorDialog : public Gtk::Dialog {
private:
  Glib::ustring icon_name_;

  IconSelector  selector_;
  Gtk::Button   add_button_;
  Gtk::Button   remove_button_;

protected:
  virtual void on_realize();

public:
  void set_icon_name(const Glib::ustring &name);
  Glib::ustring get_icon_name();

  IconSelectorDialog(Gtk::Window         &parent,
                     const Glib::ustring &icon_name = Glib::ustring());
};

class CellRendererIcon : public Gtk::CellRendererPixbuf {
private:
  sigc::signal<void, const Glib::ustring &, const Glib::ustring &> signal_edited_;
public:
  inline sigc::signal<void, const Glib::ustring &, const Glib::ustring &>
  signal_edited() {
    return signal_edited_;
  }

private:
  Gtk::Window &parent_;

  Glib::ustring icon_name_;
  Glib::ustring editing_path_;

  DialogWrapper<IconSelectorDialog> dialog_;

protected:
  void dialog_on_response(int response_id);

  virtual bool activate_vfunc(GdkEvent *event, Gtk::Widget &widget,
                              const Glib::ustring &path,
                              const Gdk::Rectangle &background_area,
                              const Gdk::Rectangle &cell_area,
                              Gtk::CellRendererState flags);

public:
  void set_icon_name(const Glib::ustring &name);

  CellRendererIcon(Gtk::Window &parent);
};

}/*pref*/
}/*gpyp*/

#endif/*PREF_ICON_H_*/
